package com.sdyeda.readiot.api;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;
import com.sdyeda.readiot.tools.HexTools;

public class IotYanyi implements IotBase {

	private static final int size = 21;
	private byte[] sendbuff = new byte[size];
	private byte[] databuff;
	// 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20
	// 头（2）动作 数据长度 保留 |传感器编号，8字节 |操作时间6字节 |校验和
	// AA 75 10 高字在前 00 | | |

	public IotYanyi() {
		clearBuffer();
	}

	@Override
	public byte[] MakeSendBuff(String id) {
		return MakeSendBuff(id, Command.read);
	}

	@Override
	public byte[] MakeSendBuff(String id, Command command) {
		// 头55AA，长度第4字节固定值0x0E=14
		//setHead();
		sendbuff[0] = (byte) 0xAA;
		sendbuff[1] = (byte) 0x75;
		sendbuff[2]= (command == Command.reset)?(byte) 0x80:(byte) 0x10; 
		sendbuff[4] = (byte) 0x0E; // 数据长度，14字节
		//id  从第6字节开始，长度8字节
		System.arraycopy(HexTools.hexStringToByteArray(id), 0, sendbuff, 6, 8);
		//time 从第14字节开始，长度6字节 例如2023年1约2日=20230102
		System.arraycopy(HexTools.getBytesTimeBCD(), 0, sendbuff, 14, 6); // 年月日
		setCRC();
		return sendbuff;
	}
	@Override
	public List<Command> Skill() {
		List<Command> result = new ArrayList<IotBase.Command>();
		result.add(Command.read);
		result.add(Command.reset);
		return result;
	}
	@Override
	public String DecodeToJson(byte[] receive) {
		return JSONObject.toJSONString(DecodeToMap(receive));
	}
	// 通用传感器
	// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F|
	// 传感器编号8字节           |BCD时间6字节    |温度*0.1|
	// 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F|
	// 测量值-偏移值-应变频-补偿频-|单位 4字节|类型|自编号16字节
	// 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F|
	// --------------------------------------|型号8字节
	// 30 31 32 33 34|总计53字节
	@Override
	public Map<String, Object> DecodeToMap(byte[] receive) {
		getData(receive);
		if (databuff == null)
			return null;

		Map<String, Object> result = new HashMap<String, Object>();
		//id 0-8字节
		result.put("id", (databuff.length >= 8) ? HexTools.bytesToHexString(databuff, 0, 8) : null);
		// 时间
		result.put("time", getTime());
		result.put("temp", (databuff.length >= 16) ? deCodeInt(14) * 0.1 : null); 	// 温度
		result.put("value", (databuff.length >= 18) ? deCodeInt(16) : null); 		// 测量值--原值
		result.put("offset", (databuff.length >= 20) ? deCodeInt(18) : null); 		// 偏移值--原值
		result.put("strain", (databuff.length >= 22) ? deCodeInt(20) * 0.1 : null); // 应变频率
		result.put("compen", (databuff.length >= 24) ? deCodeInt(22) * 0.1 : null); // 补偿频率

		result.put("unit", (databuff.length >= 28) ? toGB2312(24, 4) : null); 		// 单位
		result.put("strid", (databuff.length >= 45) ? toGB2312(29, 16) : null);		// 自编号-字符串？
		result.put("strtype", (databuff.length >= 53) ? toGB2312(45, 8) : null); 	// 设备类型-字符串

		return result;
	}

	@Override
	public String toString(byte[] buff) {
		if(buff!=null) {
			return HexTools.bytesToHex(buff);
		}
		else {
			return "";
		}
	}

	// 内部函数
	private void clearBuffer() {
		for (int i = 0; i < size; i++)
			sendbuff[i] = 0;
	}


	private void setCRC() {
		byte check = 0;
		for (int i = 0; i < sendbuff.length - 1; i++) {
			check ^= sendbuff[i];
		}
		sendbuff[size - 1] = check;
	}



	// --------------|
	// 以下是分析接收buff函数

	// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F|
	// AA 75 命令 长 度 00 data----一般53字节
	// 10 1F|
	// ----
	// 20 3F|
	// ---- SUM
	// 30 31 32 33 34 35 36 37 38 39 40 4A|总计60字节
	private void getData(byte[] receive) {
		int seek = findHead(receive);
		if (seek <= 0) {
			databuff = null;
			return;
		}

		// 数据长度
		byte[] dlbuff = new byte[2];
		System.arraycopy(receive, seek + 3, dlbuff, 0, 2);
		// System.out.println(HexTools.byte2ToInt(datalength));
		int datalength = HexTools.byte2ToInt(dlbuff);

		databuff = new byte[datalength + 7];
		if (receive.length >= datalength + 7) {
			System.arraycopy(receive, seek, databuff, 0, receive.length);
			if (!checkCRC()) {
				databuff = null;
			}
		} else {
			databuff = null;
			return;
		}

	}

	int findHead(byte[] buff) {
		byte[] head = { (byte) 0x55, 0x7A };
		byte[] temp = new byte[2];
		for (int i = 0; i < buff.length - 2; i++) {
			System.arraycopy(buff, i, temp, 0, 2);
			if (Arrays.equals(temp, head)) {
				return i;
			}
		}
		return -1; // 在剩下60字节也未发现
	}

	boolean checkCRC() {

		int size = databuff.length;
		byte check = databuff[0];
		for (int i = 1; i < size - 1; i++) {
			check ^= databuff[i];
		}
		// System.out.println(check == buf[size - 1]);
		return (check == databuff[size - 1]);
	}


	private Date getTime() {
		if (databuff.length >= 16) {
			byte[] bcdtime = new byte[6];
			System.arraycopy(databuff, 8, bcdtime, 0, 6);
			return HexTools.BytesBCDtoDate(bcdtime);
		} else {
			return new Date();
		}
	}
	
	//两字节int值
	int deCodeInt(int pos) {
		byte[] by = new byte[2];
		by[0] = by[1] = (byte)0x00;
		System.arraycopy(databuff, pos, by, 0, 2);
		return HexTools.byte2ToInt(by);
	}
	
	String toGB2312(int from,int len) {
		byte[] data = new byte[len];
		System.arraycopy(sendbuff, 24, data, 0, len);
		try {
			return new String(data, "GB2312").trim();
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}



}
